import 'package:flutter/material.dart';
import 'package:flutter_study/flutter/_18%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/state/redux_count_state.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

/*
  Redux：单向数据流架构
  1. 所有的状态都储存在Store里。这个Store会放在App顶层
  2. View使用Store存储的状态更新视图，View与用户交互产生新视图并更新状态
  3. 使用Redux不能让View直接操作数据，而是通过发起一个action来告诉Reducer更新状态
  4. 此时Reducer接收到了这个action，遍历action表，然后找匹配的action，根据该action生成新的状态并把新的状态放到Store
  5. Store丢弃老的状态对象，储存了新的状态对象后，就通知所有使用到了这个状态的View更新（类似setState），这样就能够同步不同view中的状态了
 */
void main() {
  /*
  如果要进行全局状态管理，需要创建顶层Store：
  Store接收一个reducer，以及初始化State
   */
  final store =
      Store<CountState>(reducer, initialState: CountState.initState());

  runApp(MyApp(store));
}

class MyApp extends StatelessWidget {
  final Store<CountState> _store;

  MyApp(this._store);

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: _store,
      child: MaterialApp(
        title: 'Redux',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          splashColor: Colors.transparent,
        ),
        home: HomePage(),
      ),
    );
  }
}

// 使用StoreConnector，他通过StoreProvider找到顶层的store。而且能够在state发生变化时rebuilt Widget
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('redux状态管理'),
      ),
      floatingActionButton: StoreConnector<CountState, VoidCallback>(
        builder: (ctx, callback) {
          return FloatingActionButton(
            onPressed: callback,
            child: Icon(Icons.add),
          );
        },
        // 发出Action，改变状态
        converter: (store) {
          return () => store.dispatch(StoreAction.increment);
        },
      ),
      body: Center(
        child: StoreConnector<CountState, int>(
            builder: (ctx, count) {
              return Center(
                child: Text(
                  '当前计数:$count',
                  style: Theme.of(context).textTheme.headline4,
                ),
              );
            },
            // 数据转换：将Store转化成实际ViewModel将要使用的信息，比如我们这里实际上要使用的是count
            converter: (store) => store.state.count),
      ),
    );
  }
}
